/*
|-----------------------------------------------------------------------------|
| Overall ANTLR Grammar File Structure |
|-----------------------------------------------------------------------------|
| «grammarType» grammar name;
| «optionsSpec» = options { ... }
| «tokensSpec» = tokens { ... }
| «attributeScopes» = «@action-scope-name::action-name» { ... }
| «actions»
| // rules
| rule1 : ... ;
| rule2 : ... ;
| ...
|_____________________________________________________________________________|
| «grammarType» = ( lexer | parser | tree | <empty> )
| «optionsSpec» = options { ... }
| «tokensSpec» = tokens { ... }
| «attributeScopes» =
| «actions» = @«action-scope-name»::«action-name» { ... }
| «action-scope-name» = ( lexer | parser | tree | <empty> = parser )
| «action-name» = ( header | members | rulecatch | synpredgate )
|-----------------------------------------------------------------------------|
*/
/**
* @asignatura: Procesadores de Lenguajes.
* @autor: Anthony Vittorio Russo Cabrera
* @curso: 2012/2013
* @práctica: 07 - YACC
*
*/
parser grammar YACCParser;

  options {
    language = Java;
    output = AST;
    tokenVocab = YACCLexer;
    backtrack=true;
    memoize=true;
    k=2;
  }// options

  @parser::header {
    package pl.p07.antlr3;
  }//header
  @parser::members {
  }// members

//= Grammar Rules YACC =======================================================|
doumentYACC
	: definiciones BlockDivider (regla)+ (BlockDivider rulesC )? EOF
	;

	// Sección 1
	definiciones
		: (BeginCopyBlock rulesC EndCopyBlock)?
		  (yacc_declarations)*
		;

		yacc_declarations
			: start
			| token
			| type
			| left
			| right
			| union
			| nonassoc
			;

			start
				: DefStart Identifier
				;

			token
				: DefToken (tag)? (Identifier)+
				;

			type
				: DefType (tag)? (Identifier)+
				;

			left
				: DefLeft (tag)? (Identifier|constant)+
				;

			right
				: DefRight (tag)? (Identifier|constant)+
				;

			union
				: DefUnion LeftBracket struct_declaration_list RightBracket
				;

			nonassoc
				: DefNonAssoc (tag)? (Identifier)+
				;

				tag
				  : Less Identifier Greater
				  ;

	// Sección 2
	regla
		: Identifier Colon altList SemiColon
		;

		altList
			: altpair (Stick altpair)*
			;

			altpair
				: (terminal)*
				;

				terminal
					: (Identifier|constant) (prec)? (compound_statement)?
					;

					prec
						: DefPrec (Identifier)+
						;

  // Sección 3
//= Grammar Rules C ==========================================================|
rulesC
  : (include)* (define)* (external_declaration)*
  ;

  include
    : NumberSign Include 
      ( Less Identifier ( Dot Identifier )? Greater
      | StringLiteral ) 
    ;

  define
    : NumberSign Define Identifier constant
    ;

  external_declaration
    : declaration
    | function_prototype
    | function_definition
    ;
//-----------------------------------------------------------------------------
// F u n c t i o n s

  function_prototype
    : type_specifier f1=function_header
      {System.out.println($f1.name + " es un prototipo");}
      (Comma fn=function_header
      {System.out.println($fn.name + " es un prototipo");})*
      SemiColon
    ;

  function_definition
    : type_specifier function_header 
      {System.out.println($function_header.name + " es una definición");}
      compound_statement
      
    ;

    function_header returns [String name]
    @init {
      $name = null; // for now you must init here rather than in 'returns'
    }// init
      : Identifier LeftParenthesis ( parameter_type_list )? RightParenthesis
        { $name = $Identifier.text; }
      ;

      parameter_type_list
        : parameter_list (Comma Ellipsis)?
        | Void
        ;

        parameter_list
          : parameter_declaration (Comma parameter_declaration)*
          ;

          parameter_declaration
            : declaration_specifiers (declarator)*
            ;

  function_invocation returns [String name]
  @init {
    $name=null; // for now you must init here rather than in 'returns'
  }// init
    : Identifier LeftParenthesis ( argument_expression_list )? RightParenthesis
      { $name = $Identifier.text; }
    ;
  
    argument_expression_list
      : conditional_expression (Comma conditional_expression)*
      ;

//-----------------------------------------------------------------------------
// D e f i n i t i o n
    
    declaration
      : Typedef declaration_specifiers init_declarator_list SemiColon // special case, looking for typedef 
      | (declaration_specifiers)? init_declarator_list SemiColon
      ;
    
      declaration_specifiers
        : (type_qualifier)? type_specifier
        ;
        
        type_qualifier
        : Const
        ;
      
        type_specifier
        : Void
        | Char
        | Int
        | Float
        | Double
        | struct_or_union_specifier
        | type_id
        ;
      
          type_id
          : //.{isTypeName(input.LT(1).getText())}?
            Identifier
            //.{System.out.println($Identifier.text+" is a type");}
          ;

          struct_or_union_specifier
          options {k=3;}
            : struct_or_union Identifier? LeftBracket struct_declaration_list RightBracket
            | struct_or_union Identifier
            ;

            struct_or_union
              : Struct
              | Union
              ;

            struct_declaration_list
              : (struct_declaration)+
              ;

              struct_declaration
                : specifier_qualifier_list struct_declarator_list SemiColon
                ;

                specifier_qualifier_list
                  : ( type_qualifier | type_specifier )+
                  ;

                struct_declarator_list
                  : struct_declarator (Comma struct_declarator)*
                  ;

                  struct_declarator
                    : declarator (Colon conditional_expression)?
                    | Colon conditional_expression
                    ;

      init_declarator_list
        : init_declarator (Comma init_declarator)*
        ;
      
        init_declarator
          : declarator (Assing conditional_expression)?
          ;
      
          declarator
            : pointer? direct_declarator
            | pointer
            ;
      
            pointer
              : Asterisk (type_qualifier)+ (pointer)?
              | Asterisk pointer
              | Asterisk
              | LeftSquareBracket RightSquareBracket (type_qualifier)+ (pointer)?
              | LeftSquareBracket RightSquareBracket pointer
              | LeftSquareBracket RightSquareBracket
              ;
      
            direct_declarator
              : ( Identifier
                  //.{
                  //.  if ($declaration::isTypedef) {
                  //.    //$Symbols::types.add($Identifier.text);
                  //.    System.out.println("define type "+$Identifier.text);
                  //.  }// if
                  //.}
                | LeftParenthesis declarator RightParenthesis
                )
                declarator_suffix
              ;
      
              declarator_suffix
                :   (LeftSquareBracket conditional_expression RightSquareBracket)*
                ;
//-----------------------------------------------------------------------------
// E x p r e s s i o n s
expression
  : assignment_expression (Comma assignment_expression)*
  ;

  assignment_expression
    : lvalue assignment_operator assignment_expression
    | conditional_expression
    ;

    lvalue
      : unary_expression
      ;

    assignment_operator
      : Assing
      | MultiplyEqual
      | DivideEqual
      | ModEqual
      | AddEqual
      | SubEqual
      | LeftShiftEqual
      | RightShiftEqual
      | AndEqual
      | ExpEqual
      | OrEqual
      ;

    conditional_expression
      : logical_not_expression (Question expression Colon conditional_expression)?
      ;

      logical_not_expression
        : (Not)? logical_or_expression
        ;

        logical_or_expression
          : logical_and_expression (Or logical_and_expression)*
          ;
  
          logical_and_expression
            : equality_expression (And equality_expression)*
            ;
  
            equality_expression
              : relational_expression ((Equal|NotEqual) relational_expression)*
              ;
  
              relational_expression
                : additive_expression ( ( Less | Greater | LessEqual | GreaterEqual ) additive_expression )*
                ;
  
                additive_expression
                  : (multiplicative_expression) (Plus multiplicative_expression | Minus multiplicative_expression)*
                  ;
  
                  multiplicative_expression
                    : (cast_expression) (Asterisk cast_expression | Slash cast_expression | Percent cast_expression)*
                    ;
  
                    cast_expression
                      : unary_expression
                      | function_invocation
                      //| LeftParenthesis type_name RightParenthesis cast_expression
                      ;
  
                      unary_expression
                        : postfix_expression
                        | unary_operator postfix_expression
                        | postfix_expression unary_operator
                        ;
  
                        unary_operator
                          : Increase
                          | Decrease
                          | Plus
                          | Minus
                          ;
  
                        postfix_expression
                          :   primary_expression
                                ( LeftSquareBracket expression RightSquareBracket
                                | Dot Identifier
                                )*
                          ;
  
                          primary_expression
                            : Identifier
                            | constant
                            | LeftParenthesis expression RightParenthesis
                            ;
  
                            constant
                                : HexLiteral
                                | OctalLiteral
                                | DecimalLiteral
                                | CharacterLiteral
                                | StringLiteral
                                | FloatingPointLiteral
                                | True
                                | False
                                | DefReturns // only for YACC
                                ;
//-----------------------------------------------------------------------------
// S t a t e m e n t s

compound_statement
  : LeftBracket
      (declaration | statement_list )*
    RightBracket
  ;

statement_list
  : ( statement )+
  ;

statement
  : labeled_statement
  | compound_statement
  | expression_statement
  | selection_statement
  | iteration_statement
  | jump_statement
  ;

  labeled_statement
    : Case conditional_expression Colon statement
    | Default Colon statement
    ;

  expression_statement
    : SemiColon
    | expression SemiColon
    ;

  selection_statement
    : if_statement
    | switch_statement
    ;

    if_statement
      : If LeftParenthesis expression RightParenthesis statement (options {k=1; backtrack=false;}: Else statement)?
      ;

    switch_statement
      : Switch LeftParenthesis expression RightParenthesis statement
      ;

  iteration_statement
    : while_statement
    | do_while_statement
    | for_statement
    ;

    for_statement
      : For LeftParenthesis (expression_statement|declaration) expression_statement expression? RightParenthesis statement        
      ;

    while_statement
      : While LeftParenthesis expression RightParenthesis statement
      ;

    do_while_statement
      : Do statement While LeftParenthesis expression RightParenthesis SemiColon
      ;

  jump_statement
    : Goto Identifier SemiColon
    | Continue SemiColon
    | Break SemiColon
    | Return SemiColon
    | Return expression SemiColon
    ;